<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Admin\Service\Payment;

use Admin\Data\Common;
use Laminas\Config\Writer\PhpArray;
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Exception\PayPalConnectionException;
use PayPal\Rest\ApiContext;

class PayPalService
{
    private $config = [];
    private $payPalConfig = [];
    private $payPal;
    private $intPaymentCurrency = ['JPY'];

    public function __construct()
    {
        if(!$this->config) {
            $this->config = Common::getPaymentConfig('payPal');
        }

        $this->payPal = new ApiContext(new OAuthTokenCredential($this->config['clientId']['content'], $this->config['clientSecret']['content']));
        $this->payPal->setConfig([
            'mode' => $this->config['paymentType']['selected'],
            'http.ConnectionTimeOut' => 30
        ]);
    }

    public function savePaymentConfig(array $data, $paymentConfig, $configFile)
    {
        $configArray = PaymentForm::setFormValue($paymentConfig, $data);

        $write = new PhpArray();
        $write->setUseBracketArraySyntax(true);
        $write->toFile($configFile, $configArray);

        Common::opcacheInvalidate($configFile);
    }

    public function getFormInput($paymentConfig)
    {
        return PaymentForm::createFormInput($paymentConfig);
    }

    /**
     * 订单支付
     * @param array $data
     */
    public function orderPaymentTo(array $data)
    {
        $orderInfo = $data['orderInfo'];
        $goodsArray= $orderInfo->getOrderGoods();

        $shipping   = 0;//运费
        $taxPrice   = 0;//税费
        $price      = $orderInfo->getOrderAmount();//商品价格
        $currency   = $orderInfo->getCurrencyCode();
        $orderNumber= $orderInfo->getOrderSn();

        if (in_array($currency, $this->intPaymentCurrency)) $price = intval($price);
        $total  = $price;

        $payer  = new Payer();
        $payer->setPaymentMethod('paypal');

        $itemList = new ItemList();
        $item = new Item();
        $item->setName((count($goodsArray) == 1 ? $goodsArray[0]->getGoodsName() : '多商品合并购买'))->setCurrency($currency)->setQuantity(1)->setPrice($price);
        $itemList->addItem($item);

        $details = new Details();
        $details->setShipping($shipping)->setTax($taxPrice)->setSubtotal($price);

        $amount = new Amount();
        $amount->setCurrency($currency)->setTotal($total)->setDetails($details);

        $transaction = new Transaction();
        $transaction->setAmount($amount)->setItemList($itemList)->setInvoiceNumber($orderNumber);

        $redirectUrls = new RedirectUrls();
        $redirectUrls->setReturnUrl($data['returnUrl'] . '?success=true')->setCancelUrl($data['cancelUrl'] . '?success=false');

        $payment = new Payment();
        $payment->setIntent('sale')->setPayer($payer)->setRedirectUrls($redirectUrls)->setTransactions([$transaction]);

        try {
            $payment->create($this->payPal);
        } catch (PayPalConnectionException $e) {
            //die($e->getData());
        }

        $paymentUrl = $payment->getApprovalLink();
        header("Location: {$paymentUrl}");
        exit();
    }

    /**
     * 发货处理
     * @param array $data
     */
    public function orderToSend(array $data)
    {

    }

    /**
     * 订单支付回调
     * @param $orderInfo
     * @return array|false[]
     */
    public function orderPaymentReturn($orderInfo)
    {
        $success = trim($_GET['success']);

        if($success == 'false' && !isset($_GET['paymentId']) && !isset($_GET['PayerID'])) {
            return ['paymentStatus' => false, 'message' => '取消付款'];
        }

        $paymentId  = trim($_GET['paymentId']);
        $PayerID    = trim($_GET['PayerID']);
        if(!isset($success, $paymentId, $PayerID)) {
            return ['paymentStatus' => false, 'message' => '支付失败'];
        }

        if((bool)$_GET['success'] === 'false') {
            return ['paymentStatus' => false, 'message' => '支付失败，支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】'];
        }

        if ($success == 'true') {
            $payment = Payment::get($paymentId, $this->payPal);
            $execute = new PaymentExecution();
            $execute->setPayerId($PayerID);

            $transaction    = new Transaction();
            $amount         = new Amount();
            $details        = new Details();

            $price      = $orderInfo->getOrderAmount();//商品价格
            if (in_array($orderInfo->getCurrencyCode(), $this->intPaymentCurrency)) $price = intval($price);

            $shipping   = 0;//运费
            $taxPrice   = 0;//税费

            $details->setShipping($shipping)->setTax($taxPrice)->setSubtotal($price);
            $amount->setCurrency($orderInfo->getCurrencyCode());
            $amount->setTotal($price);
            $amount->setDetails($details);
            $transaction->setAmount($amount);
            $execute->addTransaction($transaction);
            try {
                $payment->execute($execute, $this->payPal);
            } catch (\Exception $e) {
                return ['paymentStatus' => false, 'message' => '支付失败，支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】'];
            }

            return ['paymentStatus' => true, 'orderAmount' => $orderInfo->getOrderAmount(), 'message' => '支付成功'];
        }
        return ['paymentStatus' => false];
    }

    /**
     * 订单支付异步回调（未使用）
     */
    public function orderPaymentNotify()
    {

    }

    /**
     * 支付
     * @param array $data
     */
    public function paymentTo(array $data)
    {
        $payer  = new Payer();
        $payer->setPaymentMethod('paypal');

        if (in_array($data['currency'], $this->intPaymentCurrency)) $data['amount'] = intval($data['amount']);

        $itemList = new ItemList();
        $item = new Item();
        $item->setName($data['subject'])->setCurrency($data['currency'])->setQuantity(1)->setPrice($data['amount']);
        $itemList->addItem($item);

        $details = new Details();
        $details->setSubtotal($data['amount']);

        $amount = new Amount();
        $amount->setCurrency($data['currency'])->setTotal($data['amount'])->setDetails($details);

        $transaction = new Transaction();
        $transaction->setAmount($amount)->setItemList($itemList)->setInvoiceNumber($data['sn']);

        $redirectUrls = new RedirectUrls();
        $redirectUrls->setReturnUrl($data['returnUrl'] . '?success=true')->setCancelUrl($data['cancelUrl'] . '?success=false');

        $payment = new Payment();
        $payment->setIntent('sale')->setPayer($payer)->setRedirectUrls($redirectUrls)->setTransactions([$transaction]);

        try {
            $payment->create($this->payPal);
        } catch (PayPalConnectionException $e) {
            //die($e->getData());
        }

        $paymentUrl = $payment->getApprovalLink();
        header("Location: {$paymentUrl}");
        exit();
    }

    /**
     * 支付返回
     * @param array $data
     * @return array|false[]
     */
    public function paymentReturn(array $data)
    {
        $success = trim($_GET['success']);

        if($success == 'false' && !isset($_GET['paymentId']) && !isset($_GET['PayerID'])) {
            return ['paymentStatus' => false, 'message' => '取消付款'];
        }

        $paymentId  = trim($_GET['paymentId']);
        $PayerID    = trim($_GET['PayerID']);
        if(!isset($success, $paymentId, $PayerID)) {
            return ['paymentStatus' => false, 'message' => '支付失败'];
        }

        if((bool)$_GET['success'] === 'false') {
            return ['paymentStatus' => false, 'message' => '支付失败，支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】'];
        }

        if ($success == 'true') {
            $payment = Payment::get($paymentId, $this->payPal);
            $execute = new PaymentExecution();
            $execute->setPayerId($PayerID);

            $transaction    = new Transaction();
            $amount         = new Amount();
            $details        = new Details();

            if (in_array($data['currency'], $this->intPaymentCurrency)) $data['amount'] = intval($data['amount']);

            $details->setSubtotal($data['amount']);
            $amount->setCurrency($data['currency']);
            $amount->setTotal($data['amount']);
            $amount->setDetails($details);
            $transaction->setAmount($amount);
            $execute->addTransaction($transaction);
            try {
                $payment->execute($execute, $this->payPal);
            } catch (\Exception $e) {
                return ['paymentStatus' => false, 'message' => '支付失败，支付ID【' . $paymentId . '】,支付人ID【' . $PayerID . '】'];
            }

            return ['paymentStatus' => true, 'amount' => $data['amount'], 'message' => '支付成功'];
        }
        return ['paymentStatus' => false];
    }
}